/**
 * MIT License
 * 
 * Copyright (c) 2017 CaiDongyu
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.tunnel.common.util;

import com.tunnel.common.http.HttpPack;

public class HttpUtil {

	/*public static HttpData readData(InputStream in) throws IOException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		HttpData httpData = null;
		try { // TODO:1024字节够不够完全描述一次http请求，这里还要具体分析
			byte[] data = new byte[1024*1024*20];
			int len = 0;
			while ((len = in.read(data)) >= 0) {
				baos.write(data, 0, len);
				httpData = analyzeHttpData(baos.toByteArray());
				if (httpData != null && httpData.isOk())
					break;
			}
			if (httpData != null && httpData.getData() != null)
				httpData.setOk(true);
		} finally {
			try {
				baos.close();
			} catch (Exception ex) {
			}
		}
		return httpData;
	}*/
	
	public static HttpPack analyzeHttpData(byte[] data){
		// 数据中可能包含多个数据包
		// 每个数据包都以结束符作为结束
		byte[] headerEndFlag = "\r\n\r\n".getBytes();
		HttpPack httpPack = null;
//		System.out.println(new String(data));
		for (int i = 0; i <= data.length-headerEndFlag.length; i++) {
			if (data[i] == headerEndFlag[0]) {
				// 从这开始比对
				int j = 1;
				int k = i+1;
				for (; j < headerEndFlag.length; j++,k++) {
					if (data[k] != headerEndFlag[j]) {
						break;
					}
				}
				if(j < headerEndFlag.length){
					continue;
				}
				// 找到完全匹配了，开始拿数据包
				byte[] header = new byte[i+headerEndFlag.length];
				System.arraycopy(data, 0, header, 0, header.length);
				httpPack = new HttpPack();
				httpPack.setHeader(header);
				httpPack.setHeaderLength(header.length);//真实的头信息长度
				// 把剩余部分作为body存起来
				if(header.length < data.length){
					byte[] body = new byte[data.length-header.length];
					System.arraycopy(data, header.length, body, 0, body.length);
					httpPack.setBody(body);
				}
				break;
			}
		}
		return httpPack;
	}
	
	
	public static boolean checkBodyIsOk(HttpPack httpPack,byte[] data) {
		boolean isOk = false;
		do{
			if(httpPack == null){
				isOk = false;
				break;
			}
			
			// 根据头信息，分析数据的结构
			// if T-E: chunked, 就读, 直到流里有\r\n0\r\n\r\n
			// else if Content-Length存在, 就从头的末尾开始计算C-L个字节.
			// else 就这么一直读等服务器断开连接就好.
			byte[] headerByte = httpPack.getHeader();
	
			if (httpPack.getContentLenType() == 1) {
				int bodyLength = data.length - headerByte.length;
				if (bodyLength >= httpPack.getContentLength()) {
					isOk = true;
				}
			}else if (httpPack.getContentLenType() == 2) {
				byte[] bodyEndFlag = "\r\n0\r\n\r\n".getBytes();
				if (data[data.length-1] == bodyEndFlag[bodyEndFlag.length-1]) {
					int i=data.length-2,j=bodyEndFlag.length-2;
					for(;i>headerByte.length && j>=0;i--,j--){
						if (data[i] != bodyEndFlag[j]) {
							break;
						}
					}
					if(j < 0){
						// 找到完全匹配了，开始拿数据包
						isOk = true;
						break;
					}
				}
			}else if(httpPack.getContentLenType() == 3){
				if(httpPack.getHeaderLength() == data.length){
					//说明header解析完，就没有body了，这种Connection:close的，就是没有后续了
					isOk = true;
					break;
				}
			}else{
				//其他type情况，直接认为body不用考虑
				isOk = true;
			}
			
		}while(false);

		return isOk;
	}

	
	public static String getHost(byte[] header) {
		String content = new String(header);
		int index = content.indexOf("Host:");
		if (index > 0) {
			int end = content.indexOf("\r\n", index);
			String host = content.substring(index + "Host:".length(), end);
			return host.trim();
		}
		return "";
	}
	
	public static byte[] response400(String endPoint) {
		String content = "400 Bad Request(from "+endPoint+")";
		String http = "HTTP/1.1 400 Bad Request\r\n"+
		"Date: Sat, 31 Dec 2005 23:59:59 GMT\r\n"+
		"Content-Type: text/html;charset=ISO-8859-1\r\n"+
		"Connection: close\r\n"+
		"Content-Length: "+content.getBytes().length+"\r\n\r\n"+
		 content;
		return http.getBytes();
	}

	public static byte[] response404(String endPoint) {
		String content = "404 Not Found(from "+endPoint+")";
		String http = "HTTP/1.1 404 Not Found Request\r\n"+
		"Date: Sat, 31 Dec 2005 23:59:59 GMT\r\n"+
		"Content-Type: text/html;charset=ISO-8859-1\r\n"+
		"Connection: close\r\n"+
		"Content-Length: "+content.getBytes().length+"\r\n\r\n"+
		 content;
		return http.getBytes();
	}
	
	public static byte[] response500(String error,String endPoint) {
		String content = "500 Internal Server Error(from "+endPoint+"):"+error;
		String http = "HTTP/1.1 404 500 Internal Server Error\r\n"+
		"Date: Sat, 31 Dec 2005 23:59:59 GMT\r\n"+
		"Content-Type: text/html;charset=ISO-8859-1\r\n"+
		"Connection: close\r\n"+
		"Content-Length: "+content.getBytes().length+"\r\n\r\n"+
		 content;
		return http.getBytes();
	}
}
